
import { BasePop } from "../Base/BasePop";
import { ViewConfig } from "../EnumDefine/ViewDefine";
import { resMgr } from "./ResMgr";

export enum ViewTweenType {
    None = 1,
    ScaleAnim = 2 //大小缩放
}

export enum ViewMaskBlock {
    None = 0,
    Mask = 1,//遮罩
    Block = 1 << 1,//点击屏蔽
    Close = 1 << 2//点击空白关闭
}

export enum ViewMaskBlockType {
    None = 0,
    Block = ViewMaskBlock.Block,
    Mask_Block = ViewMaskBlock.Mask | ViewMaskBlock.Block,
    Mask_Block_Close = ViewMaskBlock.Mask | ViewMaskBlock.Block | ViewMaskBlock.Close,
}

interface ViewDelayInterface {
    config: ViewConfig
    param: any
    tween: ViewTweenType
    mask: ViewMaskBlockType
}

class ViewMgr {

    public static instance: ViewMgr = null
    public static getInstance() {
        if (!ViewMgr.instance) {
            ViewMgr.instance = new ViewMgr()
        }
        return ViewMgr.instance
    }

    constructor() {

    }

    private _viewQueue: BasePop[] = []
    private _delayQueue: ViewDelayInterface[] = []
    private _isLoading: boolean = false
    private _rootNode: cc.Node = null
    private _layerIndex = 0
    /**
     * 启动时框架调用 
     */
    public initRoot(root: cc.Node) {
        this._rootNode = root.getChildByName("viewRoot")
    }


    private updateViewVisible() {
        let visible = true
        let size = this._viewQueue.length
        if (size <= 0) return
        for (let i = size - 1; i >= 0; i--) {
            let view = this._viewQueue[i]
            if (view.node.active != visible) {
                view.node.active = visible
                visible && view.reshow()
            }
            if (visible && view.FullScreen) {
                visible = false
            }
        }
    }

    public openView(config: ViewConfig, param?: any, tween?: ViewTweenType, mask?: ViewMaskBlockType) {
        if (!this._rootNode) return
        if (this._isLoading) {
            this._delayQueue.push({ config: config, param: param, tween: tween, mask: mask })
        } else {
            this._isLoading = true
            let view = this._removeViewFromQueue(config.cls)
            if (view) {
                view.node.removeFromParent()
                view.init(param, tween, mask)
                this._addView(view)
            } else {
                let url = "Prefab/" + config.url
                resMgr.load(url, cc.Prefab).then((res: cc.Prefab) => {
                    if (res && this._rootNode) {
                        let node = cc.instantiate(res)
                        let view: BasePop = node.addComponent(config.cls)
                        view.FullScreen = config.full || true
                        // @ts-ignore
                        view.Res.addAssetRef(url, res)
                        view.ViewName = config.cls
                        view.init(param, tween, mask)
                        this._addView(view)
                    }
                })
            }
        }
    }

    private _addView(view: BasePop) {
        this._layerIndex++
        this._rootNode.addChild(view.node, this._layerIndex)
        this._viewQueue.push(view)
        this._isLoading = false
        let delayData = this._delayQueue.shift()
        if (delayData) {
            this.openView(delayData.config, delayData.param, delayData.tween, delayData.mask)
        } else {
            this.updateViewVisible()
        }
    }

    private _removeViewFromQueue(id: string): BasePop {
        for (let i = 0; i < this._viewQueue.length; i++) {
            if (this._viewQueue[i].ViewName == id) {
                let view = this._viewQueue.splice(i, 1)[0]
                return view
            }
        }
        return null
    }

    public getViewByName(name: string): BasePop {
        for (let i = 0; i < this._viewQueue.length; i++) {
            if (this._viewQueue[i].ViewName == name) {
                return this._viewQueue[i]
            }
        }
        return null
    }

    public getTopView(): BasePop {
        let size = this._viewQueue.length
        if (size <= 0) return null
        return this._viewQueue[size - 1]
    }

    public closeView(name: string, tween?: ViewTweenType) {
        let view = this._removeViewFromQueue(name)
        if (view) {
            view.dispose(tween)
            this.updateViewVisible()
        }
    }

    public clearAll() {
        this._viewQueue.forEach((view) => {
            view.dispose(ViewTweenType.None)
        })
        this._viewQueue = []
        this._rootNode = null
    }
}

export let viewMgr = ViewMgr.getInstance()